package nl.runnable.solr.xslt;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.PushbackReader;
import java.io.Reader;

import org.apache.solr.common.util.ContentStream;

/**
 * {@link ContentStream} implementation for internal use that enables the underlying streams to be reset to their
 * starting position. This is primarily useful for scanning the start of the content without reading it in its entirety.
 * <p>
 * This class is used by {@link XsltUpdateHandler} to allow a {@link DefaultTemplatesResolver} to scan for the XML root
 * element.
 * 
 * @author Laurens Fridael
 * 
 */
class PushbackContentStream implements ContentStream {

	private final ContentStream wrappedContentStream;

	private PushbackInputStream pushbackInputStream;

	private PushbackReader pushbackReader;

	private final int bufferSize;

	PushbackContentStream(final ContentStream wrappedContentStream, final int bufferSize) {
		this.wrappedContentStream = wrappedContentStream;
		this.bufferSize = bufferSize;
	}

	PushbackContentStream(final ContentStream wrappedContentStream) {
		this(wrappedContentStream, 1024);
	}

	protected ContentStream getWrappedContentStream() {
		return wrappedContentStream;
	}

	/**
	 * Resets this {@link ContentStream} so that it can be used again.
	 * 
	 * @throws IOException
	 */
	public void reset() throws IOException {
		if (pushbackInputStream != null) {
			pushbackInputStream.reset();
		}
	}

	/* Delegated operations. */

	@Override
	public String getName() {
		return wrappedContentStream.getName();
	}

	@Override
	public String getSourceInfo() {
		return wrappedContentStream.getSourceInfo();
	}

	@Override
	public String getContentType() {
		return wrappedContentStream.getContentType();
	}

	@Override
	public Long getSize() {
		return wrappedContentStream.getSize();
	}

	@Override
	public InputStream getStream() throws IOException {
		if (pushbackInputStream == null) {
			pushbackInputStream = new MarkSupportingPushbackInputStream(wrappedContentStream.getStream(), bufferSize);
		}
		return pushbackInputStream;
	}

	@Override
	public Reader getReader() throws IOException {
		if (pushbackReader == null) {
			pushbackReader = new PushbackReader(new InputStreamReader(getStream(), "UTF-8"));
		}
		return pushbackReader;
	}

}
